#include "tyledHttp.h"

SOCKET HttpServer::mainSocket;

//#define TYLETRACE Tyle::Object("putline(" #__LINE__ ");");
//#define TYLETRACE	Tyle::Object("\"sjit" %i "\\n\".!save('c:\\kimi\\x.txt');", __LINE__)

void HttpServer::createConnection()
{
  unsigned long   threadId;
	CreateThread(NULL,0x20000,&connect,0,0,&threadId);
}

//#define ASSERT(x) if (!(x)) printf("Assert failed in %s: %d\n",__FILE__,__LINE__);
#define CHECKEDCALL(x) { int r; if ((r=(x))!=0) printf("Call failed in %s: %d, error: 0x%x\n",__FILE__,__LINE__,r); }

DWORD _stdcall HttpServer::connect(void *p)
{
	SOCKADDR_IN sa;
	int s = sizeof(sa);
	SOCKET socket=accept(HttpServer::mainSocket,(sockaddr *)&sa,&s);

	if (socket==INVALID_SOCKET) return 0;

	Tyle::Object result(32, "socketOpen(%i,%i)", (int)socket, sa.sin_addr.s_addr);

	HttpServer::createConnection(); // start new one
  for(;;)
  { String buffer(0x10000);
	  //WSAOVERLAPPED over;
	  //over.hEvent=WSACreateEvent(); ASSERT( over.hEvent != WSA_INVALID_EVENT );
	  //socketerr=WSARecv(socket,wsabuf,buffers,&received,&flags,&over,NULL); //)!=SOCKET_ERROR)

	  int len = recv(socket,(char *)buffer, buffer.length(), 0);
		//Tyle::Object (100,"puttl('recv:%x');",len);
		Tyle_block();
	  if (len<=0) break;
		Tyle_stackString(buffer,len);

		Tyle::Object result(32, "socketMessage(%i,$)", (int)socket);
		len=1;
		for(int count=result.getLength(),i=0;i<count;i++)
	  {
		  Tyle::TextOutput textToSend(result[i]);
		  len = send(socket,(char *)textToSend,textToSend.length(),0);
			if (len<=0)
			{	Tyle::Object(100,"socketError(%i,%i)",(int)socket, WSAGetLastError());
				break;
			}
		}
    if (len<=0) break;

    Tyle_unblock();
	}
	Tyle::Object(100, "socketClose(%i)", (int)socket);
	Tyle_unblock();
  closesocket(socket);
  //CloseHandle(threadhandle); //todo, get handle
}

int HttpServer::start(int argc, char **argv) // returns port
{
	//Tyle_fileLogging(1);
	for(int i=1; i<argc;i++)
  	Tyle::Object((char *)argv[i]);
	//mutex = CreateMutex(NULL,FALSE,NULL);
		//ReleaseMutex(mutex);
	Tyle_stackString(argv[0]);
  if (Tyle::Object("httpPath=('\\'@$)[-1].!($==()?'':$2>>-$-1); parse(load(httpPath+'tyledHttp.tyle'))!").toInt())
  { return 0;
  }

	WSADATA     wsaData;
	CHECKEDCALL(WSAStartup(0x0202,&wsaData));

  int i,item,SocketInsize=sizeof(SOCKADDR_IN);
  struct in_addr *iaptr;

  char name[257];
  gethostname(name,sizeof(name)-1);
  HOSTENT *hp=gethostbyname(name);
	ASSERT(hp);
	
  iaptr=(in_addr *) hp->h_addr;
  char serverIp[256];
  strncpy(serverIp,inet_ntoa(*iaptr),31);
	  
//  mainSocket=WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,0,0,WSA_FLAG_OVERLAPPED);
  mainSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//IPPROTO_TCP,0,0,WSA_FLAG_OVERLAPPED);
  if (mainSocket == INVALID_SOCKET)
  { //printf("Error at socket(): %ld\n", WSAGetLastError());
    WSACleanup();
    return 0;
  }
  int port;
  SOCKADDR_IN SocketIn;
  SocketIn.sin_family=AF_INET; //memset(&SocketIn,0,sizeof(SOCKADDR_IN));
  SocketIn.sin_addr.s_addr=INADDR_ANY;
  SocketIn.sin_port=htons(port=Tyle::Object("port").toInt());
	//SHOW(SocketIn.sin_port,x);
  CHECKEDCALL(bind(mainSocket,(const SOCKADDR *) &SocketIn,sizeof(SOCKADDR_IN)));

  listen(mainSocket,SOMAXCONN);

  createConnection(); // first connection
  
  return port;
}

int HttpServer::stop()
{	
	closesocket(mainSocket);
	WSACleanup();
	return Tyle::Object("quit!;").toInt();
}
